/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "lcd.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "key.h"
#include "led.h"
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
//显示参数
#define DISPLAY_DATA 0
#define DISPLAY_PARA 1
uint8_t display_mode = DISPLAY_DATA;
//车位情况
uint8_t cnbr = 0, vnbr = 0, idle = 8;
float fee_cnbr = 3.5, fee_vnbr = 2.0;
//PWM
_Bool PWM_enable = 0;
//led
uint8_t led_con;
//LCD
void LCD_Process(void)
{
	uint8_t LCD_displaybuf[20];
	
	if(display_mode == DISPLAY_DATA)
	{
		LCD_DisplayStringLine(Line1, (unsigned char *)"       Data");
		
		sprintf((char *)LCD_displaybuf,"   CNBR:%d",cnbr);
		LCD_DisplayStringLine(Line3, (unsigned char *)LCD_displaybuf);
		
		sprintf((char *)LCD_displaybuf,"   VNBR:%d",vnbr);
		LCD_DisplayStringLine(Line5, (unsigned char *)LCD_displaybuf);
		
		sprintf((char *)LCD_displaybuf,"   IDLE:%d",idle);
		LCD_DisplayStringLine(Line7, (unsigned char *)LCD_displaybuf);
	}
	else if(display_mode == DISPLAY_PARA)
	{
		LCD_DisplayStringLine(Line1, (unsigned char *)"       Para");
		
		sprintf((char *)LCD_displaybuf,"   CNBR:%-5.2f",fee_cnbr);
		LCD_DisplayStringLine(Line3, (unsigned char *)LCD_displaybuf);
		
		sprintf((char *)LCD_displaybuf,"   VNBR:%-5.2f",fee_vnbr);
		LCD_DisplayStringLine(Line5, (unsigned char *)LCD_displaybuf);
	}
}

//按键
uint32_t key_tick;
void Key_Process(void)
{
	if(uwTick - key_tick < 20) return;
	key_tick = uwTick;
	
	Key_read();
	
	if(Trg & 0x01)
	{
		LCD_Clear(Black);
		display_mode = (display_mode + 1) % 2;
	}
	if(display_mode == DISPLAY_PARA)
	{
		if(Trg & 0x02)
		{
			fee_cnbr += 0.5f;
			fee_vnbr += 0.5f;
		}
		if(Trg & 0x04)
		{
			if(fee_vnbr > 0.0f)
			{
				fee_cnbr -= 0.5f;
				fee_vnbr -= 0.5f;
			}
		}
	}
	if(Trg & 0x08)
	{
		PWM_enable = !PWM_enable;
	}
}

//PWM
void PWM_Process(void)
{
	if(PWM_enable == 1)
		TIM7 -> CCR1 = 100;
	else
		TIM7 -> CCR1 = 0;

}

//led
void LED_Process(void)
{
	if(idle > 0)
		led_con |= 0x01;
	else
		led_con &= ~0x01;
	
	if(PWM_enable == 1)
		led_con |= 0x02;
	else
		led_con &= ~0x02;
}

//串口接收
uint8_t uart_buf[2];
uint8_t	rx_buf[22];
uint8_t rx_count = 0;
uint32_t Rx_tick = 0;
_Bool rx_flag = 0;
void Rx_Process(void)
{
	if(uwTick - Rx_tick < 50)	return;
	Rx_tick = uwTick;
	
	rx_flag = 0;
	
	if(rx_count > 0 && rx_flag == 0)
		printf("Error\r\n");
	
	rx_count = 0;
	memset(rx_buf,'\0',sizeof(rx_buf));
}

//车辆信息
typedef struct
{
	uint8_t type[5];
	uint8_t code[5];
	uint8_t in_year;
	uint8_t in_month;
	uint8_t in_day;
	uint8_t in_hour;
	uint8_t in_minute;	
	uint8_t in_second;
	uint8_t pos;
	
} TYPE_CAR_INFO;
TYPE_CAR_INFO car_info[8];

//判断出入场
uint8_t	Check_Enter_Leave(uint8_t * str)
{
	uint8_t i = 0;
	for(i = 0; i < 8; i++)
	{
		if(str[0] == car_info[i].code[0] && str[1] == car_info[i].code[1] && str[2] == car_info[i].code[2] && str[3] == car_info[i].code[3])
		{
			return (i + 1);
		}
	}
	return 0;	//场内无编号
}

//串口数据处理
//CNBR:A392:200202120000
//0123456789012345678901
uint8_t temp_year,temp_month,temp_day,temp_hour,temp_minute,temp_scond;
uint8_t now_year,now_month,now_day,now_hour,now_minute,now_scond;
_Bool Check_String(uint8_t * str)
{
	uint8_t i;
	if(str[4] && str[9] && str[1] == 'N' && str[2] == 'B' && str[3] == 'R' && (str[0] == 'C' || str[0] == 'V') )
	{
		for(i = 10; i < 22; i ++)
		{
			if(str[i] < '0' || str[i] > '9')
			{
				return 0;
			}
		}
		temp_year = (str[10] - '0') * 10 + (str[11] - '0');
		temp_month = (str[12] - '0') * 10 + (str[13] - '0');
		temp_day = (str[14] - '0') * 10 + (str[15] - '0');
		temp_hour = (str[16] - '0') * 10 + (str[17] - '0');
		temp_minute = (str[18] - '0') * 10 + (str[19] - '0');
		temp_scond = (str[20] - '0') * 10 + (str[21] - '0');
		
		if((temp_year>99) || (temp_month>12) || (temp_day>31) || (temp_hour>23) || (temp_minute>59) || (temp_scond>59))
			return 0;
		now_year = temp_year;
		now_month = temp_month;
		now_day = temp_day;
		now_hour = temp_hour;
		now_minute = temp_minute;
		now_scond = temp_scond;
		return 1;
	}
	else
		return 0;
}

//找车位,返回空闲车位
uint8_t Check_in_pos(void)
{
	uint8_t i;
	for(i = 0; i < 8; i ++)
	{
		if(car_info[i].pos == 0)
			return (i+1);	//返回1~8
	}
	return 0;
}

//串口回调
uint8_t temp_code[4];
uint8_t car_out_pos = 0;
uint8_t car_in_pos = 0;
int fee_second;
int fee_hour;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	Rx_tick = uwTick;	
	rx_buf[rx_count ++] = uart_buf[0];
	
	HAL_UART_Receive_IT(&huart1,uart_buf,1); //重新开启下一次接收
	
	if(rx_count == 22)
	{
		rx_count = 0;
		if(Check_String(rx_buf))
		{
			temp_code[0] = rx_buf[5];
			temp_code[1] = rx_buf[6];
			temp_code[2] = rx_buf[7];
			temp_code[3] = rx_buf[8];
			car_out_pos = Check_Enter_Leave(temp_code);
			if(car_out_pos == 0)	//入场
			{
				//找空闲车位并占用
				car_in_pos = Check_in_pos();
				//车位满
				if(car_in_pos == 0)
				{
					printf("Error\r\n");
					return;
				}
				//没满
				else
				{
					//类型
					car_info[car_in_pos - 1].type[0] = rx_buf[0];
					car_info[car_in_pos - 1].type[1] = rx_buf[1];
					car_info[car_in_pos - 1].type[2] = rx_buf[2];
					car_info[car_in_pos - 1].type[3] = rx_buf[3];
					//编号
					car_info[car_in_pos - 1].code[0] = rx_buf[5];
					car_info[car_in_pos - 1].code[1] = rx_buf[6];
					car_info[car_in_pos - 1].code[2] = rx_buf[7];
					car_info[car_in_pos - 1].code[3] = rx_buf[8];
					//时间
					car_info[car_in_pos - 1].in_year = now_year;
					car_info[car_in_pos - 1].in_month = now_month;
					car_info[car_in_pos - 1].in_day = now_day;
					car_info[car_in_pos - 1].in_hour = now_hour;
					car_info[car_in_pos - 1].in_minute = now_minute;
					car_info[car_in_pos - 1].in_second = now_scond;
					//位置
					car_info[car_in_pos - 1].pos = car_in_pos;
					
					if(rx_buf[0] == 'C')
					{
						cnbr ++;
						idle --;
					}
					else
					{
						vnbr ++;
						idle --;
					}
				}
			}
			else					//离场
			{
				fee_second = (now_year - car_info[car_out_pos - 1].in_year)*365*24*60*60 + (now_month - car_info[car_out_pos - 1].in_month)*30*24*60*60+
						     (now_day - car_info[car_out_pos - 1].in_day)*24*60*60 + (now_hour - car_info[car_out_pos - 1].in_hour)*60*60+
							 (now_minute - car_info[car_out_pos - 1].in_minute)*60 + (now_scond - car_info[car_out_pos - 1].in_second);
				if(fee_second < 0)
				{
					printf("Error\r\n");
					return;
				}
				fee_hour = (fee_second + 3599)/ 3600;
				printf("%s:%s:%d:%.2f\r\n",car_info[car_out_pos - 1].type,car_info[car_out_pos - 1].code,fee_hour,fee_hour * (rx_buf[0] == 'C'?fee_cnbr:fee_vnbr));
				if(rx_buf[0] == 'C')
				{
					cnbr --;
					idle ++;
				}
				else
				{
					vnbr --;
					idle ++;
				}
				memset(&car_info[car_in_pos - 1],0,sizeof(car_info[car_in_pos - 1]));
			}
		}
		else	
		{
			rx_flag = 1;
			printf("Error\r\n");
		}
	}
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM17_Init();
  MX_USART1_UART_Init();
  HAL_UART_Receive_IT(&huart1,uart_buf,1);
  /* USER CODE BEGIN 2 */

    LCD_Init();
	TIM17 -> CCR1 = 0;
	HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

    LCD_Clear(Black);
    LCD_SetBackColor(Black);
    LCD_SetTextColor(White);

    while (1)
    {
    /* USER CODE END WHILE */
		LCD_Process();
		Key_Process();
		PWM_Process();
		LED_Process();
		LED_Crtl(led_con);
		Rx_Process();
    /* USER CODE BEGIN 3 */
    }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
       tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
